浏览器缓存

# 1.浏览器缓存过程
- 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
- 浏览器每次拿到返回的请求结果,都会将结果和缓存标识存入浏览器缓存中
# 2.浏览器缓存机制
缓存分为强缓存和协商缓存
强缓存优先于协商缓存进行,若强缓存生效则直接使用缓存,若不生效则使用协商缓存
协商缓存由服务器决定是否使用缓存,若协商缓存生效,则返回304,直接使用缓存;若协商缓存失效,则返回200和新的资源及缓存标识,并且存入浏览器中
如果强缓存和协商缓存都没有设置,那么浏览器会采用启发式的算法,通常会取响应头中的 Date 减去 Last-Modified 的值的 10% 作为缓存时间
# 3.强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,返回 200。强缓存可以通过设置两种 HTTP 请求头实现:Expires 和 Cache-Control
ExpiresExpires 是 HTTP/1.0 中控制网页缓存的字段,其值为服务器返回该请求的结果缓存的到期时间,即再次发送请求时,如果客户端的时间小于 Expires 的值时,直接使用缓存的结果。Expires 的值是一个绝对时间,一般对应服务端时间,如果客户端与服务端的时间由于某些原因发生误差,那么强缓存将直接失效
Cache-ControlCache-Control 是 HTTP/1.1 中控制网页缓存的字段,主要取值为
- public:所有内容都将被缓存(客户端和代理服务器都可缓存)
- private:所有内容只有客户端可以缓存
- no-cache:客户端缓存内容,是否使用缓存则需要经过协商缓存来验证决定
- no-store:所有内容都不会被缓存,既不使用强缓存,也不使用协商缓存
- max-age:max-age=xxx (xxx is numeric)表示缓存内容将在xxx秒后失效
- s-maxage(单位为s):同max-age作用一样,只在代理服务器中生效(比如CDN缓存)。比如当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。max-age用于普通缓存,而s-maxage用于代理缓存。s-maxage的优先级高于max-age。如果存在s-maxage,则会覆盖掉max-age和Expires header
- max-stale:能容忍的最大过期时间,在该时间内,即使缓存过期,也使用该缓存
- min-fresh:能容忍的最小新鲜度
Expires 和 Cache-Control 对比
Expires 是 HTTP/1.0 的产物,Cache-Control 是 HTTP/1.1 的产物,两者同时存在时,Cache-Control 的优先级高于 Expires
# 4.协商缓存
协商缓存是在强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
- 协商缓存生效,返回 304 和 Not Modified
- 协商缓存失效,返回 200 和响应结果
协商缓存可以通过设置两种 HTTP header 实现:Last-Modified 和 ETag
Last-Modified 和 If-Modified-Since浏览器在第一次访问资源时,服务器返回资源的同时,在响应头上添加 Last-Modified 的 header,值就是这个资源在服务器上的最后修改时间,浏览器接收后缓存结果和 header。
浏览器下一次请求该资源时,浏览器检测到有 Last-Modified 这个 header,于是添加 If-Modified-Since 这个请求头,值就是 Last-Modified 的值,服务器再次接收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回 304 和空的响应体,浏览器直接从缓存中读取结果;如果 If-Modified-Since 的值小于服务器中这个资源的最后修改时间,则说明资源有更新,返回 200 和更新后的资源(包括新的 Last-Modified)
存在的弊端:
- 如果本地打开缓存文件,即使没有对文件进行修改,还是会造成 Last-Modified 的变化,服务端不能命中缓存导致发送相同的资源
- 因为 Last-Modified 只能以秒计时,如果在不可感知的时间内修改了资源,那么服务端会认为资源还是命中了,不会返回更新后的资源
ETag 和 If-None-MatchETag 是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,ETag 就会重新生成。浏览器再下一次请求资源时,会将上一次返回的 ETag 的值放到请求头里的 If-None-Match 里,服务器只需要比较客户端传来的 If-None-Match 跟服务器上该资源的 ETag 的值是否一致,如果一致,返回 304 和空的响应体,浏览器直接从缓存中读取结果;如果不一致,则返回 200 和更新后的资源(包括新的 ETag)
Last-Modified 和 ETag 对比
- 精度上,ETag 要优于 Last-Modified。Last-Modified 的时间单位是秒,如果某个文件在一秒内修改了多次,那么该文件的 Last-Modified 并没有体现出修改,而 ETag 使用文件的唯一标识确保了精度;如果是负载均衡的服务器,各个服务器生成的 Last-Modified 的值也可能不一样
- 性能上,Last-Modified 要优于 ETag
- 优先级上,服务器优先考虑 ETag